package com.lcf.system.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.lcf.framework.enums.RedisLockPrefixEnum;
import com.lcf.framework.exception.SysException;
import com.lcf.framework.utils.RedisLockUtils;
import com.lcf.framework.utils.UserUtils;
import com.lcf.system.dao.SysUserDao;
import com.lcf.system.dto.user.LoginDTO;
import com.lcf.system.dto.user.OpenSafeDTO;
import com.lcf.system.entity.SysUser;
import com.lcf.system.service.AuthService;
import com.lcf.wx.entity.WxUser;
import jakarta.annotation.Resource;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;

/**
 * 用户表(User)表服务实现类
 *
 * @author lcf
 * @since 2025-02-19 13:27:56
 */
@Service("authService")
public class AuthServiceImpl extends ServiceImpl<SysUserDao, SysUser> implements AuthService {
    @Resource
    private WxMaService wxMaService;
    @Resource
    private RedisLockUtils redisLockUtils;

    @Override
    public SaTokenInfo login(LoginDTO login) {
        SysUser user = Db.lambdaQuery(SysUser.class)
                .eq(SysUser::getUsername, login.getUsername())
                .eq(SysUser::getPassword, UserUtils.passwordEncrypt(login.getPassword()))
                .one();

        if (user == null) {
            throw new SysException("账号或密码错误!");
        }

        //登录
        StpUtil.login(user.getId());

        return StpUtil.getTokenInfo();
    }

    /**
     * 小程序授权
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SaTokenInfo miniAppLogin(String code) {
        try {
            String openId = wxMaService.getUserService().getSessionInfo(code).getOpenid();

            return redisLockUtils.tryLock(RedisLockPrefixEnum.WX_LOGIN, openId, () -> {
                WxUser wxUser = Db.lambdaQuery(WxUser.class).eq(WxUser::getOpenId, openId).one();
                if (wxUser == null) {
                    wxUser = new WxUser(openId, "编号" + RandomUtil.randomNumbers(6));
                    wxUser.insert();
                }

                StpUtil.login(wxUser.getId());
                return StpUtil.getTokenInfo();
            });
        } catch (WxErrorException e) {
            throw new SysException(e);
        }
    }

    @Override
    public void openSafe(OpenSafeDTO openSafe) {
        SysUser sysUser = Db.lambdaQuery(SysUser.class).select(SysUser::getPassword).eq(SysUser::getId, UserUtils.getUserId()).one();

        if (!Objects.equals(sysUser.getPassword(), UserUtils.passwordEncrypt(openSafe.getPassword()))) {
            throw new SysException("密码错误!");
        }

        // 密码正确，为当前会话打开二级认证，有效期为120秒
        StpUtil.openSafe(120);
    }
}

